import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import 'package:macless_haystack/accessory/accessory_icon.dart';
import 'package:macless_haystack/accessory/accessory_model.dart';
import 'package:macless_haystack/accessory/accessory_registry.dart';
import 'package:macless_haystack/location/location_model.dart';
import 'package:macless_haystack/map/CustomTileProvider.dart';
import 'package:provider/provider.dart';
import 'package:flutter_map_cancellable_tile_provider/flutter_map_cancellable_tile_provider.dart';
import 'package:proj4dart/proj4dart.dart' as proj4;

class AccessoryMap extends StatefulWidget {
  final MapController? mapController;

  /// Displays a map with all accessories at their latest position.
  const AccessoryMap({
    super.key,
    this.mapController,
  });

  @override
  State<StatefulWidget> createState() {
    return _AccessoryMapState();
  }
}
class _AccessoryMapState extends State<AccessoryMap> {
  LocationModel locationM = LocationModel();
  late MapController _mapController;
  void Function()? cancelLocationUpdates;
  void Function()? cancelAccessoryUpdates;

  @override
  void initState() {
    super.initState();
    _mapController = widget.mapController ?? MapController();

    var accessoryRegistry =
        Provider.of<AccessoryRegistry>(context, listen: false);
    var locationModel = Provider.of<LocationModel>(context, listen: false);

    // Resize map to fit all accessories at initial location
    fitToContent(accessoryRegistry.accessories,
        locationModel.wgs84ToGcj02(locationModel.here));

    // Fit map if first location is known
    void listener() {
      // Only use the first location, cancel further updates
      cancelLocationUpdates?.call();
      fitToContent(accessoryRegistry.accessories,
          locationModel.wgs84ToGcj02(locationModel.here));
    }

    locationModel.addListener(listener);
    cancelLocationUpdates = () => locationModel.removeListener(listener);

    // Fit map if accessories change?
  }

  @override
  void dispose() {
    super.dispose();

    cancelLocationUpdates?.call();
    cancelAccessoryUpdates?.call();
  }

  void fitToContent(List<Accessory> accessories, LatLng? hereLocation) async {
    // Delay to prevent race conditions
    await Future.delayed(const Duration(milliseconds: 500));

    List<LatLng> points = [];
    if (hereLocation != null) {
      _mapController
        ..move(hereLocation, _mapController.camera.zoom)
        ..move(
            _mapController.camera.center, _mapController.camera.zoom + 0.00001);
      points = [hereLocation];
    }

    List<LatLng> accessoryPoints = accessories
        .where((accessory) => accessory.isActive)
        .where((accessory) => accessory.lastLocation != null)
        .map((accessory) => locationM.wgs84ToGcj02(accessory.lastLocation!)!)
        .toList();
    if (accessoryPoints.isNotEmpty) {
      _mapController.fitCamera(CameraFit.bounds(
          bounds: LatLngBounds.fromPoints([...points, ...accessoryPoints])));
    }
  }

  static List<double> _calculateBaiduScales() {
    const level = 21;
    final scales = <double>[];
    scales.add(pow(2, 18).toDouble());
    for (var i = 1; i < level; i++) {
      scales.add(pow(2, (18 - i)).toDouble());
    }
    return scales;
  }

  @override
  Widget build(BuildContext context) {
    return Consumer2<AccessoryRegistry, LocationModel>(builder:
        (BuildContext context, AccessoryRegistry accessoryRegistry,
            LocationModel locationModel, Widget? child) {
      // Zoom map to fit all accessories on first accessory update
      var accessories = accessoryRegistry.accessories;
      //fitToContent(accessories, locationModel.wgs84ToGcj02(locationModel.here));

      // 1. 定义百度地图的投影（使用 proj4dart）
      /* final baiduProjection = proj4.Projection.add(
        'EPSG:3857_Baidu',
        '+proj=merc +a=6378206 +b=6356802.624 +lat_ts=0.0 +lon_0=0.0 +x_0=0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs',
      );

      // 2. 计算百度地图的分辨率（scales）
      final resolutions = _calculateBaiduScales();

      // 3. 定义 CRS（使用 CustomCrs，因为 Proj4Crs 不能直接构造）
      final baiduCrs = Proj4Crs.fromFactory(
        code: 'EPSG:3857',
        // transformation: const Transformation(1, 0, -1, 0), // 调整 Y 轴方向（TMS）
        proj4Projection: baiduProjection,
        resolutions: resolutions,
        origins: [Point(0, 0)],
        bounds: Rect.fromLTRB(
          0,
          20037508.342789244,
          20037508.342789244,
          0,
        ),
      ); */

      return FlutterMap(
        mapController: _mapController,
        options: MapOptions(
            initialCenter: locationModel.wgs84ToGcj02(locationModel.here) ??
                const LatLng(39.907270, 116.391213),
            maxZoom: 18.0,
            minZoom: 2.0,
            /* maxZoom: 21.0,
            minZoom: 3.0,  
            crs: baiduCrs,*/
            initialZoom: 14.0,
            backgroundColor: Theme.of(context).colorScheme.surface,
            interactionOptions: const InteractionOptions(
                enableMultiFingerGestureRace: true,
                flags: InteractiveFlag.pinchZoom |
                    InteractiveFlag.drag |
                    InteractiveFlag.doubleTapZoom |
                    InteractiveFlag.scrollWheelZoom |
                    InteractiveFlag.flingAnimation |
                    InteractiveFlag.pinchMove |
                    InteractiveFlag.pinchZoom)),
        children: [
          /* TileLayer(
              tileProvider: CancellableNetworkTileProvider(),
              // tms: true,
              urlTemplate:
                  'http://online{s}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&scaler=1&p=1',
              subdomains: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
          ), */
          TileLayer(
            tileProvider: CustomTileProvider(),
            tileBuilder: (context, child, tile) {
              var isDark = (Theme.of(context).brightness == Brightness.dark);
              return isDark
                  ? ColorFiltered(
                      colorFilter: const ColorFilter.matrix([
                        -1,
                        0,
                        0,
                        0,
                        255,
                        0,
                        -1,
                        0,
                        0,
                        255,
                        0,
                        0,
                        -1,
                        0,
                        255,
                        0,
                        0,
                        0,
                        1,
                        0,
                      ]),
                      child: child,
                    )
                  : child;
            },
            urlTemplate:
                "https://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
            subdomains: ['1', '2', '3', '4'],
          ),
          MarkerLayer(
            markers: [
              ...accessories
                  .where((accessory) => accessory.isActive)
                  .where((accessory) => accessory.lastLocation != null)
                  .map((accessory) => Marker(
                        rotate: true,
                        width: 50,
                        height: 50,
                        point: locationM.wgs84ToGcj02(accessory.lastLocation!)!,
                        child: AccessoryIcon(
                            icon: accessory.icon, color: accessory.color),
                      )),
            ],
          ),
          MarkerLayer(markers: [
            if (locationModel.here != null)
              Marker(
                width: 25.0,
                height: 25.0,
                point: locationM.wgs84ToGcj02(locationModel.here!)!,
                child: Stack(
                  children: [
                    Container(
                      decoration: BoxDecoration(
                        color: Theme.of(context).colorScheme.surface,
                        shape: BoxShape.circle,
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(5),
                      child: Container(
                        decoration: BoxDecoration(
                          color:
                              Colors.blue, //Theme.of(context).indicatorColor,
                          shape: BoxShape.circle,
                        ),
                      ),
                    ),
                  ],
                ),
              ),
          ]),
        ],
      );
    });
  }
}
